#pragma once

#define VMCS_ENCODE_COMPONENT( access, type, width, index )    ( unsigned )( ( unsigned short )( access ) | \
                                                                        ( ( unsigned short )( index ) << 1 ) | \
                                                                        ( ( unsigned short )( type ) << 10 ) | \
                                                                        ( ( unsigned short )( width ) << 13 ) )


#define VMCS_ENCODE_COMPONENT_FULL( type, width, index )    VMCS_ENCODE_COMPONENT( full, type, width, index )
#define VMCS_ENCODE_COMPONENT_FULL_16( type, index )        VMCS_ENCODE_COMPONENT_FULL( type, word, index )
#define VMCS_ENCODE_COMPONENT_FULL_32( type, index )        VMCS_ENCODE_COMPONENT_FULL( type, doubleword, index )
#define VMCS_ENCODE_COMPONENT_FULL_64( type, index )        VMCS_ENCODE_COMPONENT_FULL( type, quadword, index )

enum __vmcs_access
{
    full = 0,
    high = 1
};

enum __vmcs_type
{
    control = 0,
    readonly,
    guest,
    host
};

enum __vmcs_width
{
    word = 0,
    quadword,
    doubleword,
    natural
};

enum __vmcs_fields
{
    // Natural Guest Register State Fields
    GUEST_CR0 = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 0),
    GUEST_CR3 = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 1),
    GUEST_CR4 = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 2),
    GUEST_ES_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 3),
    GUEST_CS_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 4),
    GUEST_SS_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 5),
    GUEST_DS_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 6),
    GUEST_FS_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 7),
    GUEST_GS_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 8),
    GUEST_LDTR_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 9),
    GUEST_TR_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 10),
    GUEST_GDTR_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 11),
    GUEST_IDTR_BASE = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 12),
    GUEST_DR7 = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 13),
    GUEST_RSP = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 14),
    GUEST_RIP = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 15),
    GUEST_RFLAGS = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 16),
    GUEST_PENDING_DEBUG_EXCEPTION = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 17),
    GUEST_SYSENTER_ESP = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 18),
    GUEST_SYSENTER_EIP = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 19),
    GUEST_S_CET = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 20),
    GUEST_SSP = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 21),
    GUEST_INTERRUPT_SSP_TABLE_ADDR = VMCS_ENCODE_COMPONENT_FULL(guest, natural, 22),

    // 64-bit Guest Register State Fields
    GUEST_VMCS_LINK_POINTER = VMCS_ENCODE_COMPONENT_FULL_64(guest, 0),
    GUEST_DEBUG_CONTROL = VMCS_ENCODE_COMPONENT_FULL_64(guest, 1),
    GUEST_PAT = VMCS_ENCODE_COMPONENT_FULL_64(guest, 2),
    GUEST_EFER = VMCS_ENCODE_COMPONENT_FULL_64(guest, 3),
    GUEST_PERF_GLOBAL_CONTROL = VMCS_ENCODE_COMPONENT_FULL_64(guest, 4),
    GUEST_PDPTE0 = VMCS_ENCODE_COMPONENT_FULL_64(guest, 5),
    GUEST_PDPTE1 = VMCS_ENCODE_COMPONENT_FULL_64(guest, 6),
    GUEST_PDPTE2 = VMCS_ENCODE_COMPONENT_FULL_64(guest, 7),
    GUEST_PDPTE3 = VMCS_ENCODE_COMPONENT_FULL_64(guest, 8),
    GUEST_BNDCFGS = VMCS_ENCODE_COMPONENT_FULL_64(guest, 9),
    GUEST_RTIT_CTL = VMCS_ENCODE_COMPONENT_FULL_64(guest, 10),
    GUEST_PKRS = VMCS_ENCODE_COMPONENT_FULL_64(guest, 11),

    // 32-Bit Guest Register State Fields
    GUEST_ES_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 0),
    GUEST_CS_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 1),
    GUEST_SS_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 2),
    GUEST_DS_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 3),
    GUEST_FS_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 4),
    GUEST_GS_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 5),
    GUEST_LDTR_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 6),
    GUEST_TR_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 7),
    GUEST_GDTR_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 8),
    GUEST_IDTR_LIMIT = VMCS_ENCODE_COMPONENT_FULL_32(guest, 9),
    GUEST_ES_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 10),
    GUEST_CS_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 11),
    GUEST_SS_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 12),
    GUEST_DS_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 13),
    GUEST_FS_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 14),
    GUEST_GS_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 15),
    GUEST_LDTR_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 16),
    GUEST_TR_ACCESS_RIGHTS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 17),
    GUEST_INTERRUPTIBILITY_STATE = VMCS_ENCODE_COMPONENT_FULL_32(guest, 18),
    GUEST_ACTIVITY_STATE = VMCS_ENCODE_COMPONENT_FULL_32(guest, 19),
    GUEST_SMBASE = VMCS_ENCODE_COMPONENT_FULL_32(guest, 20),
    GUEST_SYSENTER_CS = VMCS_ENCODE_COMPONENT_FULL_32(guest, 21),
    GUEST_VMX_PREEMPTION_TIMER_VALUE = VMCS_ENCODE_COMPONENT_FULL_32(guest, 23),

    // 16-Bit Guest Register State Fields
    GUEST_ES_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 0),
    GUEST_CS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 1),
    GUEST_SS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 2),
    GUEST_DS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 3),
    GUEST_FS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 4),
    GUEST_GS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 5),
    GUEST_LDTR_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 6),
    GUEST_TR_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(guest, 7),
    GUEST_GUEST_INTERRUPT_STATUS = VMCS_ENCODE_COMPONENT_FULL_16(guest, 8),
    GUEST_PML_INDEX = VMCS_ENCODE_COMPONENT_FULL_16(guest, 9),

    // Natural Host Register State Fields
    HOST_CR0 = VMCS_ENCODE_COMPONENT_FULL(host, natural, 0),
    HOST_CR3 = VMCS_ENCODE_COMPONENT_FULL(host, natural, 1),
    HOST_CR4 = VMCS_ENCODE_COMPONENT_FULL(host, natural, 2),
    HOST_FS_BASE = VMCS_ENCODE_COMPONENT_FULL(host, natural, 3),
    HOST_GS_BASE = VMCS_ENCODE_COMPONENT_FULL(host, natural, 4),
    HOST_TR_BASE = VMCS_ENCODE_COMPONENT_FULL(host, natural, 5),
    HOST_GDTR_BASE = VMCS_ENCODE_COMPONENT_FULL(host, natural, 6),
    HOST_IDTR_BASE = VMCS_ENCODE_COMPONENT_FULL(host, natural, 7),
    HOST_SYSENTER_ESP = VMCS_ENCODE_COMPONENT_FULL(host, natural, 8),
    HOST_SYSENTER_EIP = VMCS_ENCODE_COMPONENT_FULL(host, natural, 9),
    HOST_RSP = VMCS_ENCODE_COMPONENT_FULL(host, natural, 10),
    HOST_RIP = VMCS_ENCODE_COMPONENT_FULL(host, natural, 11),
    HOST_S_CET = VMCS_ENCODE_COMPONENT_FULL(host, natural, 12),
    HOST_SSP = VMCS_ENCODE_COMPONENT_FULL(host, natural, 13),
    HOST_INTERRUPT_SSP_TABLE_ADDR = VMCS_ENCODE_COMPONENT_FULL(host, natural, 14),

    // 64-bit Host Register State Fields
    HOST_PAT = VMCS_ENCODE_COMPONENT_FULL_64(host, 0),
    HOST_EFER = VMCS_ENCODE_COMPONENT_FULL_64(host, 1),
    HOST_PERF_GLOBAL_CTRL = VMCS_ENCODE_COMPONENT_FULL_64(host, 2),
    HOST_PKRS = VMCS_ENCODE_COMPONENT_FULL_64(host, 3),

    // 32-bit Host Register State Fields
    HOST_SYSENTER_CS = VMCS_ENCODE_COMPONENT_FULL_32(host, 0),

    // 16-bit Host Register State Fields
    HOST_ES_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 0),
    HOST_CS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 1),
    HOST_SS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 2),
    HOST_DS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 3),
    HOST_FS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 4),
    HOST_GS_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 5),
    HOST_TR_SELECTOR = VMCS_ENCODE_COMPONENT_FULL_16(host, 6),

    // Natural Control Register State Fields
    CONTROL_CR0_GUEST_HOST_MASK = VMCS_ENCODE_COMPONENT_FULL(control, natural, 0),
    CONTROL_CR4_GUEST_HOST_MASK = VMCS_ENCODE_COMPONENT_FULL(control, natural, 1),
    CONTROL_CR0_READ_SHADOW = VMCS_ENCODE_COMPONENT_FULL(control, natural, 2),
    CONTROL_CR4_READ_SHADOW = VMCS_ENCODE_COMPONENT_FULL(control, natural, 3),
    CONTROL_CR3_TARGET_VALUE_0 = VMCS_ENCODE_COMPONENT_FULL(control, natural, 4),
    CONTROL_CR3_TARGET_VALUE_1 = VMCS_ENCODE_COMPONENT_FULL(control, natural, 5),
    CONTROL_CR3_TARGET_VALUE_2 = VMCS_ENCODE_COMPONENT_FULL(control, natural, 6),
    CONTROL_CR3_TARGET_VALUE_3 = VMCS_ENCODE_COMPONENT_FULL(control, natural, 7),

    // 64-bit Control Register State Fields
    CONTROL_BITMAP_IO_A_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 0),
    CONTROL_BITMAP_IO_B_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 1),
    CONTROL_MSR_BITMAPS_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 2),
    CONTROL_VMEXIT_MSR_STORE_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 3),
    CONTROL_VMEXIT_MSR_LOAD_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 4),
    CONTROL_VMENTER_MSR_LOAD_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 5),
    CONTROL_VMCS_EXECUTIVE_POINTER = VMCS_ENCODE_COMPONENT_FULL_64(control, 6),
    CONTROL_PML_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 7),
    CONTROL_TSC_OFFSET = VMCS_ENCODE_COMPONENT_FULL_64(control, 8),
    CONTROL_VIRTUAL_APIC_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 9),
    CONTROL_APIC_ACCESS_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 10),
    CONTROL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 11),
    CONTROL_VM_FUNCTION_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_64(control, 12),
    CONTROL_EPT_POINTER = VMCS_ENCODE_COMPONENT_FULL_64(control, 13),
    CONTROL_EOI_EXIT_BITMAP_0 = VMCS_ENCODE_COMPONENT_FULL_64(control, 14),
    CONTROL_EOI_EXIT_BITMAP_1 = VMCS_ENCODE_COMPONENT_FULL_64(control, 15),
    CONTROL_EOI_EXIT_BITMAP_2 = VMCS_ENCODE_COMPONENT_FULL_64(control, 16),
    CONTROL_EOI_EXIT_BITMAP_3 = VMCS_ENCODE_COMPONENT_FULL_64(control, 17),
    CONTROL_EPTP_LIST_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 18),
    CONTROL_VMREAD_BITMAP_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 19),
    CONTROL_VMWRITE_BITMAP_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 20),
    CONTROL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(control, 21),
    CONTROL_XSS_EXITING_BITMAP = VMCS_ENCODE_COMPONENT_FULL_64(control, 22),
    CONTROL_ENCLS_EXITING_BITMAP = VMCS_ENCODE_COMPONENT_FULL_64(control, 23),
    CONTROL_SUB_PAGE_PERMISSION_TABLE_POINTER = VMCS_ENCODE_COMPONENT_FULL_64(control, 24),
    CONTROL_TSC_MULTIPLIER = VMCS_ENCODE_COMPONENT_FULL_64(control, 25),
    CONTROL_ENCLV_EXITING_BITMAP = VMCS_ENCODE_COMPONENT_FULL_64(control, 27),

    // 32-bit Control Register State Fields
    CONTROL_PIN_BASED_VM_EXECUTION_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_32(control, 0),
    CONTROL_PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_32(control, 1),
    CONTROL_EXCEPTION_BITMAP = VMCS_ENCODE_COMPONENT_FULL_32(control, 2),
    CONTROL_PAGE_FAULT_ERROR_CODE_MASK = VMCS_ENCODE_COMPONENT_FULL_32(control, 3),
    CONTROL_PAGE_FAULT_ERROR_CODE_MATCH = VMCS_ENCODE_COMPONENT_FULL_32(control, 4),
    CONTROL_CR3_TARGET_COUNT = VMCS_ENCODE_COMPONENT_FULL_32(control, 5),
    CONTROL_VM_EXIT_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_32(control, 6),
    CONTROL_VM_EXIT_MSR_STORE_COUNT = VMCS_ENCODE_COMPONENT_FULL_32(control, 7),
    CONTROL_VM_EXIT_MSR_LOAD_COUNT = VMCS_ENCODE_COMPONENT_FULL_32(control, 8),
    CONTROL_VM_ENTRY_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_32(control, 9),
    CONTROL_VM_ENTRY_MSR_LOAD_COUNT = VMCS_ENCODE_COMPONENT_FULL_32(control, 10),
    CONTROL_VM_ENTRY_INTERRUPTION_INFORMATION_FIELD = VMCS_ENCODE_COMPONENT_FULL_32(control, 11),
    CONTROL_VM_ENTRY_EXCEPTION_ERROR_CODE = VMCS_ENCODE_COMPONENT_FULL_32(control, 12),
    CONTROL_VM_ENTRY_INSTRUCTION_LENGTH = VMCS_ENCODE_COMPONENT_FULL_32(control, 13),
    CONTROL_TPR_THRESHOLD = VMCS_ENCODE_COMPONENT_FULL_32(control, 14),
    CONTROL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = VMCS_ENCODE_COMPONENT_FULL_32(control, 15),
    CONTROL_PLE_GAP = VMCS_ENCODE_COMPONENT_FULL_32(control, 16),
    CONTROL_PLE_WINDOW = VMCS_ENCODE_COMPONENT_FULL_32(control, 17),

    // 16-bit Control Register State Fields
    CONTROL_VIRTUAL_PROCESSOR_IDENTIFIER = VMCS_ENCODE_COMPONENT_FULL_16(control, 0),
    CONTROL_POSTED_INTERRUPT_NOTIFICATION_VECTOR = VMCS_ENCODE_COMPONENT_FULL_16(control, 1),
    CONTROL_EPTP_INDEX = VMCS_ENCODE_COMPONENT_FULL_16(control, 2),

    // Natural Read only Register State Fields
    EXIT_QUALIFICATION = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 0),
    IO_RCX = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 1),
    IO_RSI = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 2),
    IO_RDI = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 3),
    IO_RIP = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 4),
    GUEST_LINEAR_ADDRESS = VMCS_ENCODE_COMPONENT_FULL(readonly, natural, 5),

    // 64-bit Read only Register State Fields
    GUEST_PHYSICAL_ADDRESS = VMCS_ENCODE_COMPONENT_FULL_64(readonly,0),

    // 32-bit Read only Register State Fields
    VM_INSTRUCTION_ERROR = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 0),
    EXIT_REASON = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 1),
    VM_EXIT_INTERRUPTION_INFORMATION = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 2),
    VM_EXIT_INTERRUPTION_ERROR_CODE = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 3),
    IDT_VECTORING_INFORMATION_FIELD = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 4),
    IDT_VECTORING_ERROR_CODE = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 5),
    VM_EXIT_INSTRUCTION_LENGTH = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 6),
    VM_EXIT_INSTRUCTION_INFORMATION = VMCS_ENCODE_COMPONENT_FULL_32(readonly, 7),
};

